package cn.kgc.springboot.vue.shiro;

import cn.kgc.springboot.vue.entity.Permission;
import cn.kgc.springboot.vue.entity.RolePermission;
import cn.kgc.springboot.vue.entity.UserRole;
import cn.kgc.springboot.vue.mapper.PermissionMapper;
import cn.kgc.springboot.vue.mapper.RolePermissionMapper;
import cn.kgc.springboot.vue.mapper.UserRoleMapper;
import cn.kgc.springboot.vue.utils.IpUtil;
import cn.kgc.springboot.vue.utils.JWTUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAccount;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author 课工场
 * @date 2024/12/19
 * @description
 */
public class CustomerRealm extends AuthorizingRealm {


    @Resource
    private JWTUtil jwtUtil;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private UserRoleMapper userRoleMapper;

    @Resource
    private RolePermissionMapper rolePermissionMapper;

    @Resource
    private PermissionMapper permissionMapper;

    @Override
    public  boolean supports(AuthenticationToken token){
        return token instanceof  JwtToken;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        String token = (String) principals.getPrimaryPrincipal();
        Integer id = (Integer) jwtUtil.analyzingToken("userInfo", token).get("id");

        //  根据id 查询角色id
        LambdaQueryWrapper<UserRole> lambda = new QueryWrapper<UserRole>().lambda();
        lambda.eq(UserRole::getUserId,id);
        Set<Integer> rids = userRoleMapper.selectList(lambda).stream().map(userRole -> userRole.getRoleId()).collect(Collectors.toSet());

        LambdaQueryWrapper<RolePermission> lambda1 = new QueryWrapper<RolePermission>().lambda();
        lambda1.in(RolePermission::getRoleId,rids);

        Set<Integer> pIds = rolePermissionMapper.selectList(lambda1).stream()
                .map(rolePermission -> rolePermission.getPerId())
                .collect(Collectors.toSet());


        LambdaQueryWrapper<Permission> lambda2 = new QueryWrapper<Permission>().lambda();
        lambda2.in(Permission::getId,pIds)
                .eq(Permission::getIsMenu,2);

        Set<String> permissionString = permissionMapper.selectList(lambda2).stream()
                .map(permission -> permission.getPermission())
                .collect(Collectors.toSet());


        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addStringPermissions(permissionString);

        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        JwtToken jwtToken = (JwtToken) token;
        String tken  = (String) jwtToken.getPrincipal();
        System.out.println("tken = " + tken);
        // 判定token是否合法
        jwtUtil.verifyToken(tken);
        ServletRequest servletRequest = jwtToken.getServletRequest();
        String customerIp = IpUtil.getIp((HttpServletRequest) servletRequest);
        // 获取token在redis中存储的对应ip地址
        String redisIp = stringRedisTemplate.opsForValue().get(tken);

        if (!StringUtils.equals(customerIp,redisIp)){
            throw new RuntimeException("token异常...");
        }

        return new SimpleAccount(tken,tken,this.getName());
    }
}
